summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_class_token.h
blob: ab20e00ff8096299fbdd82003d3d50ba8b9c4c14 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "common/bit_util.h"
#include "common/common_types.h"

namespace Kernel {

class KAutoObject;

class KClassTokenGenerator {
public:
    using TokenBaseType = u16;

public:
    static constexpr size_t BaseClassBits = 8;
    static constexpr size_t FinalClassBits = (sizeof(TokenBaseType) * CHAR_BIT) - BaseClassBits;
    // One bit per base class.
    static constexpr size_t NumBaseClasses = BaseClassBits;
    // Final classes are permutations of three bits.
    static constexpr size_t NumFinalClasses = [] {
        TokenBaseType index = 0;
        for (size_t i = 0; i < FinalClassBits; i++) {
            for (size_t j = i + 1; j < FinalClassBits; j++) {
                for (size_t k = j + 1; k < FinalClassBits; k++) {
                    index++;
                }
            }
        }
        return index;
    }();

private:
    template <TokenBaseType Index>
    static constexpr inline TokenBaseType BaseClassToken = 1U << Index;

    template <TokenBaseType Index>
    static constexpr inline TokenBaseType FinalClassToken = [] {
        TokenBaseType index = 0;
        for (size_t i = 0; i < FinalClassBits; i++) {
            for (size_t j = i + 1; j < FinalClassBits; j++) {
                for (size_t k = j + 1; k < FinalClassBits; k++) {
                    if ((index++) == Index) {
                        return static_cast<TokenBaseType>(((1ULL << i) | (1ULL << j) | (1ULL << k))
                                                          << BaseClassBits);
                    }
                }
            }
        }
        UNREACHABLE();
    }();

    template <typename T>
    static constexpr inline TokenBaseType GetClassToken() {
        static_assert(std::is_base_of<KAutoObject, T>::value);
        if constexpr (std::is_same<T, KAutoObject>::value) {
            static_assert(T::ObjectType == ObjectType::KAutoObject);
            return 0;
        } else if constexpr (!std::is_final<T>::value) {
            static_assert(ObjectType::BaseClassesStart <= T::ObjectType &&
                          T::ObjectType < ObjectType::BaseClassesEnd);
            constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) -
                                        static_cast<TokenBaseType>(ObjectType::BaseClassesStart);
            return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
        } else if constexpr (ObjectType::FinalClassesStart <= T::ObjectType &&
                             T::ObjectType < ObjectType::FinalClassesEnd) {
            constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) -
                                        static_cast<TokenBaseType>(ObjectType::FinalClassesStart);
            return FinalClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
        } else {
            static_assert(!std::is_same<T, T>::value, "GetClassToken: Invalid Type");
        }
    };

public:
    enum class ObjectType {
        KAutoObject,

        BaseClassesStart,

        KSynchronizationObject = BaseClassesStart,
        KReadableEvent,

        BaseClassesEnd,

        FinalClassesStart = BaseClassesEnd,

        KInterruptEvent = FinalClassesStart,
        KDebug,
        KThread,
        KServerPort,
        KServerSession,
        KClientPort,
        KClientSession,
        KProcess,
        KResourceLimit,
        KLightSession,
        KPort,
        KSession,
        KSharedMemory,
        KEvent,
        KLightClientSession,
        KLightServerSession,
        KTransferMemory,
        KDeviceAddressSpace,
        KSessionRequest,
        KCodeMemory,

        // NOTE: True order for these has not been determined yet.
        KAlpha,
        KBeta,

        FinalClassesEnd = FinalClassesStart + NumFinalClasses,
    };

    template <typename T>
    static constexpr inline TokenBaseType ClassToken = GetClassToken<T>();
};

using ClassTokenType = KClassTokenGenerator::TokenBaseType;

template <typename T>
static constexpr inline ClassTokenType ClassToken = KClassTokenGenerator::ClassToken<T>;

} // namespace Kernel